<?php
namespace App\Common\Lib\Fun;

use App\Common as com;

/**
 * Class Array_
 * @version 1.2
 * @package App\Base\Lib\Fun
 */
class Array_ {


	/**
	 * 检查数据是否键名是否为默认键名
	 * @param array $array
	 * @return bool
	 */
	public static function arrayIsList( array &$array ):bool {
		if ( function_exists( 'array_is_list' ) ) {
			return array_is_list( $array );
		}
		// 检查是否严格按照数组中键的值是否从0开始排序且不能中断
		$index = 0;
		foreach( array_keys( $array ) as $arrayKey ){
			if( $arrayKey !== $index++ ){
				return false;
			}
		}
		//
		return true;
	}

	/**
	 * 分割字符串为数组，并返回数组指定位置的值
	 * @param string $delimiter 分割字符
	 * @param string $str 待分割的文本
	 * @param int $assign_site 返回的数组位置 [>=0]指定位置 [<0]结尾开始的指定位置
	 * @param mixed $default 如果数组不存在时，返回的默认值。[NULL][默认]
	 * @return str|NULL [str]文本值 [NULL]不存在
	 */
	public static function explodeGetValue( string $delimiter, string $str, $assign_site, $default = NULL ){
		$explode_array = explode( $delimiter, $str );
		if( $assign_site > 0 ){
			return $explode_array[ $assign_site ] ?? $default;
		}else{
			return $explode_array[ count( $explode_array ) + $assign_site ] ?? $default;
		}
	}
	
	/**
	 * 将字符串分隔成数组（整数数组）
	 * @param int|str|array $str 要分隔的字符(支持传入数组)
	 * @param array $param 参数数组（其他功能可参考"toArray的$param参数"） <br />
	 * ················· [可空](str)									$param['valueCallback']			说明：值回调数据[默认：intval]	<br />
	 * ················· [可空](bool)								$param['unique']				说明：是否去除重复的数组[默认：false]	<br />
	 * ················· [可空] (int|str|array|callback)	$param['filter']							说明：自动过滤的值	<br />
	 * ················· [可空] (str)								$param['delimiter']				说明：分隔符[默认：',']	<br />
	 * ················· [可空] (bool)								$param['trimSides']				说明：是否删除字符串首尾(包含分隔符)。[true:默认]清除 [false]不清除	<br />
	 * ················· [可空] (bool)								$param['trimArraySides']		说明：是否删除新数组字符串首尾(包含分隔符)。[true]清除 [false:默认]不清除	<br />
	 * ················· [可空] (int) 								$param['sort']					说明：排序 可选值 [-1：降序] [0：不排序] [1：升序]	<br />
	 * ················· [可空] (bool) 								$param['notEmpty']				说明：处理空字符串时，是否返回空数组。[true]是 [false:默认]否<br />
	 * @return array 返回分隔后的数组
	 */
	public static function toArrayInt( $str, array $param = [] ){
		//预设参数
		$param['valueCallback']  = $param['valueCallback'] ?? 'intval';
		//
		return self::toArray( $str, $param );
	}
	
	/**
	 * 将字符串分隔成数组（字符串数组）
	 * @param int|str|array $str 要分隔的字符(支持传入数组)
	 * @param array $param 参数数组 （其他功能可参考"toArray的$param参数"） <br />
	 * ················· [可空](str)									$param['valueCallback']			说明：值回调数据[默认：trim]	<br />
	 * ················· [可空](bool)								$param['unique']				说明：是否去除重复的数组[默认：false]	<br />
	 * ················· [可空] (int|str|array|callback)				$param['filter']				说明：自动过滤的值	<br />
	 * ················· [可空] (str)								$param['delimiter']				说明：分隔符[默认：',']	<br />
	 * ················· [可空] (bool)								$param['trimSides']				说明：是否删除字符串首尾(包含分隔符)。[true:默认]清除 [false]不清除	<br />
	 * ················· [可空] (bool)								$param['trimArraySides']		说明：是否删除新数组字符串首尾(包含分隔符)。[true]清除 [false:默认]不清除	<br />
	 * ················· [可空] (int) 								$param['sort']					说明：排序 可选值 [-1：降序] [0：不排序] [1：升序]	<br />
	 * @return array 返回分隔后的数组
	 */
	public static function toArrayStr( $str, array $param = [] ):array {
		//预设参数
		$param['valueCallback']  = $param['valueCallback'] ?? 'trim';
		//
		return self::toArray( $str, $param );
	}
	
	/**
	 * 将字符串分隔成数组
	 * @param int|str|array $str 要分隔的字符(支持字符串(1,2,3)、数组[1,2,3]、纯数字[1])
	 * @param array $param 参数数组 <br />
	 * ················· [可空] (str)							$param['valueCallback']			说明：值回调数据(需要返回新的值)( function( $array ){ return $array; } )	<br />
	 * ················· [可空] (bool)							$param['unique']				说明：是否去除重复的数组[默认：false]	<br />
	 * ················· [可空] (int|str|array|callback)			$param['filter']				说明：自动过滤的值	<br />
	 * ················· [可空] (str)							$param['delimiter']				说明：分隔符[默认：',']	<br />
	 * ················· [可空] (bool)							$param['trimSides']				说明：是否删除字符串首尾(包含分隔符)。[true:默认]清除 [false]不清除	<br />
	 * ················· [可空] (bool)							$param['trimArraySides']		说明：是否删除新数组字符串首尾(包含分隔符)。[true]清除 [false:默认]不清除	<br />
	 * ················· [可空] (int) 							$param['sort']					说明：排序 可选值 [-1：降序] [0：不排序] [1：升序]	<br />
	 * ················· [可空] (bool) 							$param['notEmpty']				说明：处理空字符串时，是否返回空数组。[true]是 [false:默认]否<br />
	 * ················· [可空] (str) 							$param['buildKey']				说明：是否为每个值建立数组key名<br />
	 * ················· [可空] (str) 							$param['setType']				说明：设置数组值的变量类型<br />
	 * ················· [可空/多选_A/必须] (unknown_type) $param['AAAAA']	说明：AAAAA	<br />
	 * @return array 返回分隔后的数组
	 */
	public static function toArray( $str, array $param = [] ):array {
		// 默认参数
		$param['valueCallback'] = $param['valueCallback'] ?? null;
		$param['unique'] = $param['unique'] ?? 0;
		$param['filter'] = $param['filter'] ?? null;
		$param['delimiter'] = $param['delimiter'] ?? ',';
		$param['trimSides'] = $param['trimSides'] ?? true;
		$param['trimArraySides'] = $param['trimArraySides'] ?? false;
		$param['sort'] = $param['sort'] ?? 0;
		$param['notEmpty'] = $param['notEmpty'] ?? false;
		$param['buildKey'] = $param['buildKey'] ?? null;
		$param['setType'] = $param['setType'] ?? null;
		// 分割
		if ( is_string( $str ) ) {
			// 删除字符串首尾
			if( $param['trimSides'] ){
				$trim_character_mask = $param['trimSides'] ? $param['delimiter'] : '';
				$str_trim = trim( $str, $trim_character_mask );
			}else{
				$str_trim = $str;
			}
			//
			if( $param['notEmpty'] == true && $str_trim == '' ) return [];
			//
			$str_array = explode( $param['delimiter'], $str_trim );
		}else if( is_array( $str ) ){
			$str_array = $str;
		}elseif( is_numeric( $str ) ){
			$str_array = [ $str ];
		}else{
			return [];
		}
		// 值回调
		if( isset( $param['valueCallback'] ) ){
			$str_array = array_map( $param['valueCallback'], $str_array );
		}
		// 去重复
		if( $param['unique'] ) $str_array = array_unique( $str_array );
		// 自动删除的值
		if( is_callable( $param['filter'] ) ){
			$str_array = array_filter( $str_array, $param['filter'] );
		}else if( is_array( $param['filter'] ) || is_numeric( $param['filter'] ) || is_string( $param['filter'] ) ){
			if( ! is_array( $param['filter'] ) ) $param['filter']  = [ $param['filter'] ];
			$str_array = array_filter( $str_array, function( $value ) use ( $param ){
				return ! in_array( $value, $param['filter']);
			} );
		}
		// 排序
		if( $param['sort'] == 1 ){//升序
			asort( $str_array );
		}else if( $param['sort'] == -1 ){//降序
			arsort( $str_array );
		}
		// 删除新数组首尾空白字符
		if( $param['trimArraySides'] ){
			foreach ( $str_array as &$str_array_value ){
				$str_array_value = trim( $str_array_value );
			}unset( $str_array_value );
		}

		// 设置数组值的变量类型
		if( $param['setType'] != null ){
			foreach ( $str_array as &$str_array_value ){
				if( gettype( $str_array_value ) !== $param['setType'] ){
					settype( $str_array_value, $param['setType'] );
				}
			}unset( $str_array_value );
		}
		// 重置键名
		$str_array = array_merge( $str_array );
		// 为每个值建立数组key名
		if( isset( $param['buildKey'] ) ){
			$str_array = array_map( function( $value ) use ( $param ){
				return [
					$param['buildKey'] => $value,
				];
			}, $str_array );
		}
		//
		return $str_array;
	}

	/**
	 * 多维数组的值去重（注意：不对相同的数组去重）
	 * @param array $arrays
	 * @return array
	 */
	public static function arrayUniqueOfMany( array $arrays ):array {
		foreach( $arrays as &$arrayValue ){
			if( is_array( $arrayValue ) ){
				$arrayValue = self::arrayUniqueOfMany( $arrayValue );
			}else{
				$arrayValue = array_unique( $arrayValue );
			}
		} unset( $arrayValue );
		//
		return $arrays;
	}
	
	/**
	 * 数组合并成字符串
	 * @param array $array 要合并成字符串的数组
	 * @param array $param 参数数组 <br />
	 * ················· [可空](str)		$param['glue']	说明：合并的分隔字符[默认：',']	<br />
	 * ················· [可空](bool)	$param['hasSides']	说明：首尾是否有分隔符（如果合并后的字符为空，则无效）[默认：false]	<br />
	 * ················· [可空](str)		$param['default']	说明：默认字符（合并后的字符为空时） [默认：'']	<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return string 合并后的字符
	 */
	public static function toStr( array $array, array $param = [] ):string {
		// 默认参数
		$param['glue'] = $param['glue'] ?? ',';
		$param['hasSides'] = $param['hasSides'] ?? false;
		$param['default'] = $param['default'] ?? '';
		// 合并
		$str = implode( $param['glue'], $array  );
		// 首尾是否有分隔符
		if( $param['hasSides'] && $str != '' ) $str = "{$param['glue']}{$str}{$param['glue']}";
		//
		if( $str == '' && $param['default'] != $str ) $str = $param['default'];
		//
		return $str;
	}

	/**
	 * 换成字符串ids（自动去重、排序）
	 * @param array $ids
	 * @return string 格式:",id1,id2,"
	 */
	public static function toContinuousIdsAsString( array $ids ):string {
		// 整理
		$ids = com\Lib\Fun\Array_::toArray( $ids, [
			'unique' => true,
			'sort' => 1,
		]);
		// 转字符串
		return com\Lib\Fun\Array_::toStr( $ids, [
			'hasSides' => true,
		] );
	}
	
	/**
	 * 格式化数组路径为标准格式
	 * @param string $keyPath 数组路径（默认支持：'a'、'a->0->c'、'a[]->c'、'a[3]->c'）
	 * @param array $param 参数数组 <br />
	 * ················· [可空] (str)		$param['delimiter']	说明：分隔符[默认：'->']	<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return string 返回标准格式（如：['a'][0]['b']）
	 * @throws
	 */
	public static function formatKeyPath( string $keyPath, array $param = [] ):string {
		$param['delimiter'] = $param['delimiter'] ?? '->';
		// 检查
		if( strpos( $keyPath, "{$param['delimiter']}{$param['delimiter']}" ) !== false ){
			throw com\Lib\Err\Exception::makeOfNew( '语法错误，不允许出现：->->', com\Lib\Err\Code::$undefined );
		}
		// 将 "a[]" 转为 "a->[]" 兼容两者用法
		$keyPath = str_replace( '[', "{$param['delimiter']}[", $keyPath );
		$keyPath = str_replace( "{$param['delimiter']}{$param['delimiter']}", $param['delimiter'], $keyPath ); // 合并多个"->"（上一条产生的）
		// 消除开头->
		$keyPath = ltrim( $keyPath, $param['delimiter'] );
		// 判断是否存在分隔符，如不存在则直接返回路径
		/*
		if( strpos( $keyPath, '->' ) === false ){
			if( strpos( $keyPath, '[' ) !== false && strpos( $keyPath, ']' ) !== false ) return $keyPath;
		}
		*/
		//
		$keyPath_array = explode( $param['delimiter'], $keyPath );
		$format_str = '';
		foreach ( $keyPath_array as $keyPath_value ){
			if( $keyPath_value === '[]' ){
				$format_str .= "[]";
			}else{
				if( strpos( $keyPath_value, '[' ) !== false && strpos( $keyPath_value, ']' ) !== false ){
					$format_str .= $keyPath_value;
				}else{
					$format_str .= "['{$keyPath_value}']";
				}

			}
		}
		//
		return $format_str;
	}
	
	/**
	 * 提取多维数组中的路径相同的多个值
	 * @param array $array 需要提取的数组
	 * @param string $keyPath 数组路径（支持格式：1.PHP数组访问的格式，如：['a'][0]['b']， 2."->"分割，如：a->b->c，3.纯字符串,如：'id'）
	 * @param array $param 参数数组 <br />
	 * ················· [可空](int)	$param['hasNull']	说明：结果列表是否包含null值。[0：默认]不包含 [1]包含	<br />
	 * ················· [可空](int)	$param['isStrict']	说明：是否为严格模式，严格模式开启时，数组路径必须存在，否则抛出异常。[0]宽松模式 [1：默认]严格模式	<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return array 返回单维数组，格式：[ 格式：[ 1, 2, 3, ... ] ]
	 */
	public static function extractAllAssignValue( $array, string $keyPath, array $param = [] ):array {
		$keyPath = self::formatKeyPath( $keyPath );
		//
		$param['hasNull'] = $param['hasNull'] ?? 0;
		//
		$return_array = [];
		
		foreach ( $array as $arrayValue ){
			$value = self::extractAssignValue( $arrayValue, $keyPath, [
				'formatingKeyPath' => 1,
				'isStrict' => $param['isStrict'] ?? 0,
			] );
			if( $value === null && $param['hasNull'] == 0 ) continue; //结果是否包含null值
			$return_array[] = $value;

		}
		return $return_array;
	}

	/**
	 * 返回数组中的指定字段
	 * @param array $array
	 * @param array|string $field 指定字段
	 * @return array|string
	 */
	public static function assignField( array $array, $field ) {
		if( is_array( $field ) ){
			return array_intersect_key( $array, array_flip( $field ) );
		}else{
			return $array[ $field ];
		}

	}
	
	/**
	 * 数组路径访问
	 * @param array $array 数组
	 * @param string $keyPath 数组路径（支持格式：1.PHP数组访问的格式，如：['a'][0]['b']， 2."->"分割，如：a->b->c）
	 * @param array $param 参数数组 <br />
	 * ················· [可空](int)		$param['formatingKeyPath']		说明：是否已格式化数组路径。[0：默认]没有，需要内部格式化 [1]已格式化，不需要内部格式化	<br />
	 * ················· [可空](int)		$param['isStrict']							说明：是否为严格模式，严格模式开启时，数组路径必须存在，否则抛出异常。[0]宽松模式 [1：默认]严格模式	<br />
	 * ················· [可空](int)		$param['returnQuote']					说明：是否返回值引用地址（使用时，函数调用函数前必须加上"&"才可返回引用地址）。[0：默认]否 [1]是	<br />
	 * ················· [可空](str)		$param['default']							说明：默认返回值，路径不存在时，则设置默认值	（默认：抛出异常）<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return mixed 数组路径值
	 */
	public static function &extractAssignValue( &$array, string $keyPath, array $param = [] ){
		$param['formatingKeyPath'] = $param['formatingKeyPath'] ?? 0;
		$param['isStrict'] = $param['isStrict'] ?? 1;
		$param['returnQuote'] = $param['returnQuote'] ?? 0;
		//
		//是否已格式化数组路径
		if( $keyPath !== '' && $param['formatingKeyPath'] == 0 ) $keyPath = self::formatKeyPath( $keyPath );
		//
		$keyPath_str = $keyPath;
		//是否为严格模式
		if( ! $param['isStrict'] ) $keyPath_str = "{$keyPath_str} ?? null";
		//是否返回值引用地址
		$quote_str = $param['returnQuote'] ? '&' : '' ;
		//生成PHP代码
		$arrayPhpcode = "\$arrayValue = {$quote_str}\$array{$keyPath_str};";
		//执行
		eval( $arrayPhpcode );
		//默认返回值
		if( ! isset( $arrayValue ) && ! isset( $param['default'] ) ){
			throw com\Lib\Err\Exception::makeOfNew( 'extractAssignValue方法默认值不存在', com\Lib\Err\Code::$apiSysParamError );
		}
		//
		$arrayValue ??= $param['default'];
		//
		return $arrayValue;
	}

	/**
	 * 提取多维数组的所有值，转为一维数组
	 * @param array $arrayMap
	 * @return array [ 1, 2, 3 ]
	 * 示例：$arrayMap = [ 1 [ 2, [ 3 ] ] ] 返回：[ 1, 2, 3 ]
	 */
	public static function multiToOneArray( array $arrayMap ) {
		$sonListsArray = [];
		//
		foreach ( $arrayMap as $arrayId => $arrayMapValue ){
			if( is_array( $arrayMapValue ) ){
				$sonListsArray = array_merge( $sonListsArray, self::multiToOneArray( $arrayMapValue ) );
			}else{
				$sonListsArray[] = $arrayMapValue;
			}
		}
		//返回
		return $sonListsArray;
	}

	/**
	 * 访问指定路径数组值
	 * @param array $array 数组
	 * @param string|int $keyPath 数组路径（支持格式：1.PHP数组访问的格式，如：['a'][0]['b']， 2."->"分割，如：a->b->c）
	 * @param array $param 参数数组 <br />
	 * ················· [可空] (str)	$param['delimiter']	说明：分隔符[默认：'->']	<br />
	 * ················· [可空](int)		$param['formatingKeyPath']		说明：是否已格式化数组路径。[0：默认]没有，需要内部格式化 [1]已格式化，不需要内部格式化	<br />
	 * ················· [可空](int)		$param['isStrict']				说明：是否为严格模式，严格模式开启时，数组路径必须存在，否则抛出异常。[0]宽松模式 [1：默认]严格模式	<br />
	 * ················· [可空](int)		$param['returnQuote']			说明：是否返回值引用地址（使用时，函数调用函数前必须加上"&"才可返回引用地址）。[0：默认]否 [1]是	<br />
	 * ················· [可空](str)		$param['default']				说明：默认返回值，路径不存在时，返回默认值	（默认：抛出异常）<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return mixed 数组路径值
	 * @throws
	 */
	public static function &assignPathRead( &$array, string|int $keyPath, array $param = [] ){
		$param['formatingKeyPath'] = $param['formatingKeyPath'] ?? 0;
		$param['isStrict'] = $param['isStrict'] ?? 1;
		$param['returnQuote'] = $param['returnQuote'] ?? 0;
		//
		if( array_key_exists( 'default', $param ) ){
			$param['isStrict'] = 0;
		}else{
			$param['default'] = null;
		}
		// 是否已格式化数组路径
		if( $keyPath !== '' && $param['formatingKeyPath'] == 0 ){
			$keyPath = self::formatKeyPath( $keyPath, [
				'delimiter' => $param['delimiter'] ?? null,
			] );
		}
		//
		$keyPath_str = $keyPath;
		// 是否为严格模式
		if( $param['isStrict'] === 1 ){
			if( ! self::assignPathIsset( $array, $keyPath ) ){
				throw com\Lib\Err\Exception::makeOfNew( "Undefined array key \"{$keyPath}\"", com\Lib\Err\Code::$sysDataNotExist );
			}
		}else{
			$keyPath_str = "{$keyPath_str}";
			if( $param['returnQuote'] === 0 ){
				$keyPath_str .= " ?? \$param['default']";
			}
		}
		// 是否返回值引用地址->检查数据是否存在，不存则设置为默认值
		if( $param['returnQuote'] === 1 ){
			if( ! self::assignPathIsset( $array, $keyPath ) ){
				self::assignPathWrite( $array, $keyPath, $param['default'] );
			}
		}
		$quote_str = $param['returnQuote'] ? '&' : '' ;
		//
		$arrayValue = null;
		// 生成PHP代码
		$arrayPhpCode = "\$arrayValue = {$quote_str}\$array{$keyPath_str};";
		// 执行
		eval( $arrayPhpCode );
		// 默认返回值
		if( $arrayValue === null && isset( $param['default'] ) ) $arrayValue = $param['default'];
		//
		return $arrayValue;
	}
	
	/**
	 * 写入指定路径数组值
	 * @param array &$array 数组
	 * @param string|int $keyPath 数组路径（支持格式：1.PHP数组访问的格式，如：['a'][0]['b']， 2."->"分割，如：a->b->c）
	 * @param mixed $value 设置的值
	 * @param array $param 参数数组 <br />
	 * ················· [可空] (str)	$param['delimiter']	说明：分隔符[默认：'->']	<br />
	 * ················· [可空](int)		$param['formatingKeyPath']		说明：是否已格式化数组路径。[0：默认]没有，需要内部格式化 [1]已格式化，不需要内部格式化	<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return bool 是否写入成功
	 * @throws
	 */
	public static function assignPathWrite( &$array, string|int $keyPath, $value, array $param = [] ){
		$param['formatingKeyPath'] = $param['formatingKeyPath'] ?? 0;
		//是否已格式化数组路径
		if( $keyPath !== '' && $param['formatingKeyPath'] == 0 ) $keyPath = self::formatKeyPath( $keyPath, [
			'delimiter' => $param['delimiter'] ?? null,
		] );
		//
		$keyPath_str = $keyPath;
		//生成PHP代码
		$arrayPhpcode = "\$array{$keyPath_str} = \$value;";
		//执行
		eval( $arrayPhpcode );
		//
		return true;
	}

	/**
	 * 检查指定路径是否存在
	 * @param array &$array 数组
	 * @param string|int $keyPath 数组路径（支持格式：1.PHP数组访问的格式，如：['a'][0]['b']， 2."->"分割，如：a->b->c）
	 * @param array $param 参数数组 <br />
	 * ················· [可空] (str)	$param['delimiter']	说明：分隔符[默认：'->']	<br />
	 * ················· [可空](int)		$param['formatingKeyPath']		说明：是否已格式化数组路径。[0：默认]没有，需要内部格式化 [1]已格式化，不需要内部格式化	<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return bool 是否存在。[true]存在 [false]不存在
	 */
	public static function assignPathIsset( &$array, string|int $keyPath, array $param = [] ){
		$param['formatingKeyPath'] = $param['formatingKeyPath'] ?? 0;
		//是否已格式化数组路径
		if( $keyPath !== '' && $param['formatingKeyPath'] == 0 ) $keyPath = self::formatKeyPath( $keyPath, [
			'delimiter' => $param['delimiter'] ?? null,
		] );
		//
		$keyPathStr = $keyPath;
		//生成PHP代码
		$arrayPhpcode = "\$isset = isset(\$array{$keyPathStr});";
		//执行
		eval( $arrayPhpcode );
		//
		return $isset ?? false;
	}

	/**
	 * 销毁指定路径
	 * @param array &$array 数组
	 * @param string|int $keyPath 数组路径（支持格式：1.PHP数组访问的格式，如：['a'][0]['b']， 2."->"分割，如：a->b->c）
	 * @param array $param 参数数组 <br />
	 * ················· [可空](int)		$param['formatingKeyPath']		说明：是否已格式化数组路径。[0：默认]没有，需要内部格式化 [1]已格式化，不需要内部格式化	<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return bool
	 */
	public static function assignPathUnset( &$array, string|int $keyPath, array $param = [] ):bool {
		$param['formatingKeyPath'] = $param['formatingKeyPath'] ?? 0;
		//是否已格式化数组路径
		if( $keyPath !== '' && $param['formatingKeyPath'] == 0 ) $keyPath = self::formatKeyPath( $keyPath );
		//
		$keyPathStr = $keyPath;
		//生成PHP代码
		$arrayPhpcode = "unset(\$array{$keyPathStr});";
		//执行
		eval( $arrayPhpcode );
		//
		return true;
	}

	/**
	 * 将多维数组转为单维数组，例子：[ 0 => 1, [ '2' => 2, ... ] ] 返回：[ 0 => 1, '2' => 2 ]
	 * @param array $arrays
	 * @param array $params 参数数组 <br />
	 * ················· [可空](int)		$param['mergeMode']		说明：合并模式。[0][默认]保留字符串键名，重复则覆盖	<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return array
	 */
	public static function mergeManyLayerToOne( array $arrays, array $params = [] ):array {
		$params['mergeMode'] ??= 0;
		//
		$mergeArray = [];
		//
		foreach( $arrays as $arrayKey => $arrayValue ){
			if( is_array( $arrayValue ) ){
				$mergeArrayL2 = self::mergeManyLayerToOne( $arrayValue );
				foreach( $mergeArrayL2 as $arrayL2Key => $arrayL2Value ){
					if( is_string( $arrayL2Key ) ){
						$mergeArray[ $arrayL2Key ] = $arrayL2Value;
					}else{
						$mergeArray[] = $arrayL2Value;
					}
				}
			}else if( is_string( $arrayKey ) ){
				$mergeArray[ $arrayKey ] = $arrayValue;
			}else{
				$mergeArray[] = $arrayValue;
			}
		}
		//
		return $mergeArray;
	}
	
	/**
	 * 多维数组合并(单数组的合并结果与array_merge一致，但支持多维数组)
	 * @param array $array 数组1
	 * @param array $array 数组...
	 * @param array $array 数组N
	 * @return array 合并后的数组
	 */
	public static function arrayMerges():array {
		// ...
		$fun_args = func_get_args(); // 获取参数
		$merge_array = []; // 合并后的数组
		//
		foreach ( $fun_args as $fun_arg_value ){
			$merge_array = self::arrayMerge( $merge_array, $fun_arg_value );
		}
		return $merge_array;
	}

	/**
	 * 合并数组（数组2覆盖数组1），如果两个参数数组都为null则返回null
	 * @param array $array1 数组1
	 * @param array $array2 数组2
	 * @return array|null 合并后的数组 [null]没有数据
	 */
	public static function arrayMergeOrNull( $array1, $array2 ):?array {
		if( $array1 === null && $array2 === null ){
			return null;
		}
		//
		$newArray = [];
		//
		if( $array1 !== null ){
			$newArray = array_merge( $newArray, is_array( $array1 ) ? $array1 : [ $array1 ] );
		}
		if( $array2 !== null ){
			$newArray = array_merge( $newArray, is_array( $array2 ) ? $array2 : [ $array2 ] );
		}
		//
		return $newArray;
	}

	/**
	 * 合并数组（数组2覆盖数组1）
	 * @param array $array1 数组1
	 * @param array $array2 数组2
	 * @return array 合并后的数组
	 */
	public static function arrayMerge( array $array1, array $array2 ):array {
		return self::arrayMergeOfParam( $array1, $array2 );
	}

	/**
	 * 合并数组（数组2覆盖数组1）
	 * @param array $array1 数组1
	 * @param array $array2 数组2
	 * @param array $param 参数数组 <br />
	 * ················· [可空](int)		$param['mergeIntKey']		说明：是否合并数字键名数组。[0][默认]	<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return array 合并后的数组
	 */
	public static function arrayMergeOfParam( array $array1, array $array2, array $params = [] ):array {
		$params['mergeIntKey'] = $params['mergeIntKey'] ?? 0;
		// 特殊优化->针对$array1为空数组的情况
		if( empty( $array1 )){
			return $array2;
		}
		//
		foreach ( $array2 as $array2_key => $array2_value ){
			if( is_numeric( $array2_key ) && $params['mergeIntKey'] === 0 ){
				$array1[] = $array2_value;
			}else{
				if( array_key_exists( $array2_key, $array1 ) ){
					// 如果都为数组则合并数组，不是则覆盖
					if( is_array( $array1[ $array2_key ] ) && is_array( $array2_value ) ){
						$array1[ $array2_key ] = self::arrayMerge( $array1[ $array2_key ], $array2_value );
					}else{
						$array1[ $array2_key ] = $array2_value;
					}

				}else{
					$array1[ $array2_key ] = $array2_value;
				}
			}
		}
		//
		return $array1;
	}
	
	/**
	 * 向数组插入新元素。新数组的值将被插入到数组的开头。
	 * @param array $array [传参]规定数组（结果直接传入改变量）。
	 * @param array $value1 规定要插入的值。
	 * @return array 插入后的数组
	 */
	public static function arrayUnshiftKey( &$array, $value1 ):array {
		return array_merge( $value1, $array );
	}
	
	/**
	 * 遍历搜索值是否存在数组中
	 * @param mixed $search 必需。规定要在数组搜索的值。[{string}]遍历搜索 [{array}, {array}]遍历搜索多个数组
	 * @param array $array 必需。规定要搜索的数组。
	 * @param bool $type 可选。如果设置该参数为 true，则检查搜索的数据与数组的值的类型是否相同。
	 * @return bool 是否存在。 [true]存在 [false]不存在
	 * 		$this如果给定的值 search 存在于数组 array 中则返回 true。如果第三个参数设置为 true，函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。
	 * 		如果没有在数组中找到参数，函数返回 false。
	 * 		注释：如果 search 参数是字符串，且 type 参数设置为 true，则搜索区分大小写。
	 */
	public static function inArrayErgodic( $search, array $array, bool $type = false ):bool {
		if( is_array( $search ) ){
			foreach ( $search as $search_value ){
				if( ! in_array( $search_value, $array, $type ) ) return false;
			}
			return true;
		}else{
			return in_array( $search, $array, $type );
		}
	}

	/**
	 * 如果在数组中找到指定的键值，则返回对应的键名，否则返回 FALSE。
	 * 如果在数组中找到键值超过一次，则返回第一次找到的键值所匹配的键名。
	 * @param $search
	 * @param array $array
	 * @param string|null $keyPath
	 * @param bool $type 可选。如果设置该参数为 true，则检查搜索的数据与数组的值的类型是否相同。
	 * @return false|int|string [false]不存在 [string|int]返回键名
	 */
	public static function arraySearchOfKeyPath( $search, array $array, string $keyPath = null, bool $type = false ) {
		if( $keyPath === null ){
			return array_search( $search, $array );
		}else{
			foreach( $array as $arrayKey => $arrayValue ){
				if( $type ){
					if( self::assignPathRead( $arrayValue, $keyPath ) === $search ){
						return $arrayKey;
					}
				}else{
					if( self::assignPathRead( $arrayValue, $keyPath ) == $search ){
						return $arrayKey;
					}
				}
			}
			//
			return false;
		}
	}

	/**
	 * @todo :: 时间关系不做
	 * 转换为路径数组(一维数组转多维数组)
	 * @param array $array 待转换数组
	 * @return array 转换后的数组
	 */
	/*
	public static function toPathArray( $array ){
		
	}
	*/
	
	/**
	 * 转换为路径数组(根据定义好的数组键名，将一维数组转多维数组)
	 * 示例：( [ 'a->b' => 1 ] ) 返回：[ 'a' => [ 'b' => 1 ] ]
	 * @param array $array 待转换数组
	 * @return array 转换后的数组
	 */
	public static function toPathArrayDirectKey( array $array ):array {
		$newArray = [];
		$array = com\Lib\Fun\Model::toArray( $array );
		self::toPathArrayDirectKeySubMain( $array, $newArray );
		return $newArray;
	}
	
	/**
	 * 转换为路径数组(根据定义好的数组键名，将一维数组转多维数组)->主处理器
	 * @param array $array 待转换数组
	 * @param array &$newArray 转换后的数组
	 * @return void 无返回值
	 */
	protected static function toPathArrayDirectKeySubMain( array $array = [], array &$newArray = [] ):void {
		foreach ( $array as $key => $value ){
			if( is_array( $value ) ){
				$newArray[ $key ] = [];
				self::toPathArrayDirectKeySubMain( $value, $newArray[ $key ] );
			}else{
				$keyPath = self::formatKeyPath( $key );
				self::assignPathWrite( $newArray, $keyPath, $value );
			}
		}
	}
	
	/**
	 * 将一个多维数组转换为一个一维的路径数据
	 * 如：[ 'a' => [ 'b' => [ 'c' => 1 ] ] ] 返回：[ 'a->b->c' => 1 ]
	 * @param array $array
	 * @return array
	 */
	public static function toKeyPathArray( array $array ) {
		$newKeyPathArray = [];
		//
		foreach( $array as $arrayKey =>  $arrayValue ){
			if( is_array( $arrayValue ) ){
				$keyPathArrayRes = self::toKeyPathArray( $arrayValue );
				foreach( $keyPathArrayRes as $dataKey => $dataValue ){
					$newKeyPathArray["{$arrayKey}->{$dataKey}"] = $dataValue;
				}
			}else{
				$newKeyPathArray[ $arrayKey ] = $arrayValue;
			}
		}
		//
		return $newKeyPathArray;
	}

	/**
	 * 提取数组中所有目录并转换为路径数组
	 * 如：[ 'a' => [ 'b' => [ 'c' => 1 ] ], 'c' => [ 'd' => 1 ] ] 返回：[ 'a', 'a->b', 'd' ]
	 * @param array $array
	 * @param string $delimiter 分割符.[->][默认]
	 * @return array
	 */
	public static function getDirectoryKeyPathOfArray( array $array, string $delimiter = '->' ) {
		$directoryPath = [];
		foreach( $array as $arrayKey => $arrayValue ){
			if( is_array( $arrayValue ) ){
				$directoryPath[] = $arrayKey;
				//
				$arrayRes = self::getDirectoryKeyPathOfArray( $arrayValue, $delimiter );
				foreach( $arrayRes as $arrayResValue ){
					$directoryPath[] = "{$arrayKey}{$delimiter}{$arrayResValue}";
				}
			}else{
				if( str_contains( $arrayKey, $delimiter ) ){
					$directoryPath = array_merge( $directoryPath, self::getDirectoryKeyPathOfArray( self::toPathArrayDirectKey( [ $arrayKey => $arrayValue ] ) ) );
				}

			}
		}
		//
		return $directoryPath;
	}

	/**
	 * @TODO :: 未完成
	 * 反转/交换数组中键名和键值（支持多维数组）
	 * 示例：( [ 'a->b' => 1 ] ) 返回：[ 'a' => [ 'b' => 1 ] ]
	 * @param array $array 待反转的数组
	 * @param array $param 参数数组 <br />
	 * ················· [可空](str)	$param['keyPath']	说明：str  数组路径（支持格式：1.PHP数组访问的格式，如：['a'][0]['b']， 2."->"分割，如：a->b->c）。[默认]使用系统内置函数处理(array_flip)	<br />
	 * ················· [可空](bool)	$param['mergeConflict']	说明：是否合并反转后相同键名的数组。[0][默认]否 [1]是	<br />
	 * ················· [可空](mixed)	$param['newValue']	说明：反转后的新键值	<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return array 转换后的数组
	 */
	public static function arrayFlip( $array, array $param = [] ):array {
		// ...
		$param['keyPath'] = $param['keyPath'] ?? '';
		$param['mergeConflict'] = $param['mergeConflict'] ?? false;
		$isExistParam_OfNewValue = isset( $param['newValue'] );
		// 判断是否可以使用内置函数处理
		if( $param['keyPath'] == '' && ! $param['mergeConflict'] && ! $isExistParam_OfNewValue ){
			return array_flip( $array );
		}
		//
		$newArray = [];
		foreach( $array as $arrayValue ){
			if( $param['keyPath'] == '' ){
				$newkey = $arrayValue;
			}else{
				$newkey = self::assignPathRead( $arrayValue, $param['keyPath']);
			}
			//
			if( $param['mergeConflict'] == true ){
				$newArray[ $newkey ][] = $isExistParam_OfNewValue ? $param['newValue'] : $arrayValue;
			}else{
				$newArray[ $newkey ] = $isExistParam_OfNewValue ? $param['newValue'] : $arrayValue;
			}
		}
		//
		return $newArray;
	}

	/**
	 * 数组键名命名风格转换(转为下划线)
	 * @param array $names 字符串
	 * @param bool $ucfirst 首字母是否大写（驼峰规则）
	 * @param string $char 指定分隔符。默认为"_"
	 * @return array
	 */
	public static function keyNameToParseNamesAsUnderline( array $names, bool $ucfirst = true, string $char = "_" ):array {
		return self::keyNameToParseNames( $names, 0, $ucfirst, $char );
	}

	/**
	 * 数组键名命名风格转换(转为驼峰)
	 * @param array $names 字符串
	 * @param bool $ucfirst 首字母是否大写（驼峰规则）
	 * @param string $char 指定分隔符。默认为"_"
	 * @return array
	 */
	public static function keyNameToParseNamesAsHump( array $names, bool $ucfirst = true, string $char = "_" ):array {
		return self::keyNameToParseNames( $names, 1, $ucfirst, $char );
	}

	/**
	 * 数组键名命名风格转换
	 * @param array $array 字符串
	 * @param int $type 转换类型 [0]将驼峰风格转换为下划线的风格 [1]将下划线风格转换为驼峰的风格
	 * @param bool $ucfirst 首字母是否大写（驼峰规则） [true][默认]
	 * @param string $char 指定分隔符。默认为"_"
	 * @param int|null $recursiveNum 递归转换层数。[null]全部
	 * @return array
	 */
	public static function keyNameToParseNames( array $array, int $type = 0, bool $ucfirst = true, string $char = "_", int|null $recursiveNum = null ):array {
		$newArray = [];
		//
		foreach ( $array as $key => $value ){
			// 字符串转换格式
			if( ! is_int( $key ) ){
				$key = com\Lib\Fun\Str::parseName( $key, $type, $ucfirst, $char );
			}
			//
			if( ( $recursiveNum === null || $recursiveNum >= 1 ) && is_array( $value ) ){
				$newArray[ $key ] = self::keyNameToParseNames( $value, $type, $ucfirst, $char, $recursiveNum === null ? null : $recursiveNum - 1 );
			}else{
				$newArray[ $key ] = $value;
			}
		}
		//
		return $newArray;
	}

	/**
	 * 根据规则移动数组数据，
	 * @param array $datas 多数组
	 * @param array $rule 规则
	 * 	如：	[
	 * 			'a->b' => 'c', // 移动
	 * 			'a' => null, // 删除
	 * 		]
	 * 	或：	[
	 * 			[ 'a->b', 'c' ], // 移动
	 * 			[ 'a', null ], // 删除
	 * 		]
	 * @return void
	 */
	public static function movePaths( array &$datas, array $rule ):void {
		// 检查$rule
		foreach( $rule as $ruleKey => $ruleValue ){
			if( ! is_array( $ruleValue ) && $ruleKey == '' ){
				throw com\Lib\Err\Exception::makeOfNew( 'ruleKey不能为空', com\Lib\Err\Code::$sysFunParamError );
			}
		}
		//
		foreach( $datas as &$value ){
			foreach( $rule as $ruleKey => $ruleValue ){
				// ...
				if( is_array( $ruleValue ) ){
					$ruleKey = $ruleValue[0];
					$ruleValue = $ruleValue[1];
				}
				//
				if( ! self::assignPathIsset( $value, $ruleKey ) ){
					self::assignPathUnset( $value, $ruleKey ); // @TODO :: 这里需要优化为 array_key_exists
					continue;
				}
				// 移动->复制
				if( $ruleValue !== null ){
					self::assignPathWrite( $value, $ruleValue, self::assignPathRead( $value, $ruleKey ) );
				}
				// 移动->销毁
				self::assignPathUnset( $value, $ruleKey );
			}
		}
	}

	/**
	 * 根据规则移动数组数据
	 * @param array $data 单数组
	 * @param array $rule 规则
	 * 	如：	[
	 * 			'a->b' => 'c', // 移动
	 * 			'a' => null, // 删除
	 * 		]
	 * @return void
	 */
	public static function movePath( array &$data, array $rule ):void {
		$dataQuote = [ &$data ];
		self::movePaths( $dataQuote, $rule );
	}

	/**
	 * 构建keyname为指定路径值的索引数组
	 * @param array $array 数组
	 * @param string|null $keyPath 数组路径（支持格式：1.PHP数组访问的格式，如：['a'][0]['b']， 2."->"分割，如：a->b->c） [null]直接翻转
	 * @param bool $isMany 是否合并到数组（[$keyPath][]）
	 * @param string|int|null $default 默认值。[null][默认]抛出异常
	 * @return array
	 */
	public static function buildIndexArrayOfKeyPath( array $array, string $keyPath = null, bool $isMany = false, string|int|null $default = null ):array {
		$newArray = [];
		//
		if( $keyPath === null ){
			if( $isMany ){
				$newArray[] = array_flip( $array );
			}else{
				$newArray = array_flip( $array );
			}
		}else{
			foreach( $array as $arrayValue ){
				$index = self::assignPathRead( $arrayValue, $keyPath, [
					'default' => $default,
				] );
				//
				if( $isMany ){
					$newArray[ $index ][] = $arrayValue;
				}else{
					$newArray[ $index ] = $arrayValue;
				}
			}
		}
		//
		return $newArray;
	}

	/**
	 * 追加值（如果不存在）
	 * @param array $array 必需。规定需要搜素的键值。
	 * @param mixed $value 必需。规定被搜索的数组。
	 * @param bool $strict 可选。如果该参数被设置为 TRUE，则函数在数组中搜索数据类型和值都一致的元素。[false][默认]
	 * @return void
	 */
	public static function appendValueNx( array &$array, $value, bool $strict = false ):void {
		if( array_search( $value, $array, $strict ) === false ){
			$array[] = $value;
		}
	}

	/**
	 * 连接数组的键和值
	 * @param array $array 数字
	 * @param array $array 数组
	 * @param bool $isHeadEndGlue 是否有首尾分隔符
	 * @param bool $emptyIsHeadEndGlue 值为空时是否有首尾分隔符
	 * @return string
	 */
	public static function implode( string $glue, array $array, bool $isHeadEndGlue = true, bool $emptyIsHeadEndGlue = true ):string {
		$implodeString = implode( $glue, $array );
		// 首尾分隔符
		if( $isHeadEndGlue ){
			if( $implodeString !== '' ){
				$implodeString = "{$glue}{$implodeString}{$glue}";
			}else{
				if( $emptyIsHeadEndGlue ){
					$implodeString = "{$glue}{$glue}";
				}
			}
		}
		//
		return $implodeString;
	}

	/**
	 * 连接数组的键和值
	 * @param array $array 数组	 * @param string $keyValueGlue 键和值之间的分隔符
	 * @param string $arrayGlue 每个值的分隔符
	 * @return string
	 */
	public static function implodeKeyAndValue( array $array, string $keyValueGlue, string $arrayGlue ):string {
		$res = '';
		foreach( $array as $arrayKey => $arrayValue ){
			$res .= "{$arrayKey}{$keyValueGlue}{$arrayValue}{$arrayGlue}";
		}
		//
		return ltrim( $res, $arrayGlue );
	}

	/**
	 * 移除重复值
	 * @param array $array
	 * @return array
	 */
	public function rmRepetitionValue( array $array ):array {
		return array_flip ( array_flip ( $array ) );
	}

	/**
	 * 遍历合并指定数组
	 * @param array $array 原数组
	 * @param array $mergeArray
	 * @return bool [true][必返]
	 */
	public static function foreachMerge( array &$array, array $mergeArray ):bool {
		foreach( $array as &$arrayValue ){
			$arrayValue = array_merge( $arrayValue, $mergeArray );
		} unset( $arrayValue );
		//
		return true;
	}

	/**
	 * 输出数组中的当前元素和下一个元素的值，然后把数组的内部指针重置到数组中的第一个元素：
	 * @param array $array
	 * @param bool $default 默认值，[false][默认]
	 * @return mixed 返回值
	 */
	public static function reset( array &$array, bool $default = false ) {
		$arrayReset = reset( $array );
		//
		return $arrayReset !== false ? $arrayReset : $default;
	}

	/**
	 * 函数将内部指针指向数组中的最后一个元素，并输出。
	 * @param array $array
	 * @param bool $default 默认值，[false][默认]
	 * @return mixed 返回值
	 */
	public static function end( array &$array, bool $default = false ) {
		$arrayEnd = end( $array );
		//
		return $arrayEnd !== false ? $arrayEnd : $default;
	}

	/**
	 * 比较两个数组的键值
	 * @param mixed ...$agrs
	 * @return array (注意：返回差集数组，该数组包含所有在被比较的数组（array1）中，但是不在任何其他参数数组（array2 或 array3 等等）中的键值。)
	 * @throws com\Lib\Err\BaseException\Throw_
	 */
	public static function arraysUdiffOfValueName( ...$agrs ):array {
		if( count( $agrs ) < 2 ){
			throw com\Lib\Err\Exception::makeOfNew( '', com\Lib\Err\Code::$sysFunParamError );
		}
		//
		$valueName = array_pop( $agrs );
		$agrs[] = function( $a, $b ) use ( $valueName ) {
			if( $a[ $valueName ] === $b[ $valueName ] ){
				return 0;
			}else{
				return $a[ $valueName ] > $b[ $valueName ] ? 1 : -1;
			}
		};
		//
		return array_udiff( ...$agrs );
	}

	/**
	 * 取数组值
	 * @param array $array
	 * @return array
	 */
	public static function arrayValuesMany( array $array ):array {
		$newArray = array_values( $array );
		foreach( $newArray as &$newArrayValue ){
			if( is_array( $newArrayValue ) ){
				$newArrayValue = self::arrayValuesMany( $newArrayValue );
			}
		} unset( $newArrayValue );
		//
		return $newArray;
	}

	/**
	 * 获取一列(注意：不返回null的数据)
	 * @param array $array
	 * @param string $keyPath 数组路径（支持格式：1.PHP数组访问的格式，如：['a'][0]['b']， 2."->"分割，如：a->b->c）
	 * @return array
	 */
	public static function getColumn( array $array, string $keyPath ):array {
		$column = [];
		foreach( $array as $arrayValue ){
			$value = self::assignPathRead( $arrayValue, $keyPath, [
				'default' => null,
			] );
			//
			if( $value !== null ){
				$column[] = $value;
			}
		}
		//
		return $column;
	}

	/**
	 * 获取列数据（多层）(注意：不返回null的数据)
	 * @param array $array
	 * @param string $keyPathMultilayer 多维数组路径（支持格式：1.PHP数组访问的格式，如：['a'][0]['b']， 2."->"分割，如：a->b->c，3.支持[]->lists->[]->id）
	 * @return array
	 */
	public static function getColumnOfMultilayer( array $array, string $keyPathMultilayer ):array {
		$sourceKeyPathArray = explode( '->', $keyPathMultilayer );
		//
		$lastKeyPath = end( $sourceKeyPathArray );
		if( $lastKeyPath === '[]' ){
			return self::getColumn( self::extractAllPathQuote( $array, $keyPathMultilayer ), 'valueQuote' );
		}else{
			return self::getColumn( self::extractAllPathQuote( $array, $keyPathMultilayer ), 'valueQuote->' . end( $sourceKeyPathArray ) );
		}
	}

	/**
	 * @param string $keyPathMultilayer
	 * @return string
	 */
	public static function formatKeyPathMultilayer( string $keyPathMultilayer ):string {
		// 支持"id[][]"简写
		$keyPathMultilayerMid = str_replace( '[]', '=>[]', $keyPathMultilayer );
		$keyPathMultilayerMid = str_replace( '->=>', '->', $keyPathMultilayerMid ); // 防止错误添加了空字符链接，如：'->->'
		$keyPathMultilayerMid = str_replace( '=>', '->', $keyPathMultilayerMid );
		//
		$keyPathMultilayerMid = ltrim( $keyPathMultilayerMid, '->' );
		//
		return $keyPathMultilayerMid;
	}

	/**
	 * 获取列数据Quote信息（多层）
	 * @param array $array
	 * @param string $keyPathMultilayer 多维数组路径（支持格式：1.PHP数组访问的格式，如：['a'][0]['b']， 2."->"分割，如：a->b->c，3.支持[]->lists->[]->id）
	 * @return array
	 */
	public static function &extractAllPathQuote( array &$array, string $keyPathMultilayer ):array {
		// 支持"id[][]"简写
		$keyPathMultilayerMid = self::formatKeyPathMultilayer( $keyPathMultilayer );
		//
		$sourceKeyPathArray = explode( '->', "[]->{$keyPathMultilayerMid}" ); // 默认开头添加[]
		//
		// 遍历出所有需要join的路径
		$pathsQuote = [
			[
				'valueQuote' => &$array,
			]
		];
		//
		$count = count( $sourceKeyPathArray );
		for( $i = 0; $i < ( $count - 1 ); $i++ ){
			$pathsQuote = &self::extractAllPathQuoteOne( $pathsQuote, $sourceKeyPathArray[ $i ] );
		}
		//
		return $pathsQuote;
	}

	/**
	 * 提取所有路径
	 * @param array &$sourceData
	 * @param string $keyPathValue 路径
	 * @return array
	 */
	private static function &extractAllPathQuoteOne( array &$sourceData, string $keyPathValue ) {
		$pathsQuote = [];
		foreach( $sourceData as $sourceKey => &$sourceValue ){
			if( $keyPathValue === '[]' ){
				if( ! is_array( $sourceValue['valueQuote'] ) ){
					continue;
				}
				//
				foreach( $sourceValue['valueQuote'] as &$sourceValue2 ){
					if( isset( $sourceValue['rootQuote'] ) ){
						$rootQuote = &$sourceValue['rootQuote'];
					}else{
						$rootQuote = &$sourceValue2;
					}
					//
					$pathsQuote[] = [
						'rootKey' => $sourceKey,
						'rootQuote' => &$rootQuote,
						'valueQuote' => &$sourceValue2,
					];
					unset( $pathsQuoteValue ); // 销毁是为了创建不同新的变量，防止循环时一直使用同一个变量地址
				} unset( $sourceValue2 );
			}else{
				if( isset( $sourceValue['rootQuote'] ) ){
					$rootQuote = &$sourceValue['rootQuote'];
				}else{
					$rootQuote = &$sourceValue;
				}
				//
				$pathsQuote[] = [
					'rootKey' => $sourceKey,
					'rootQuote' => &$rootQuote,
					'valueQuote' => &$sourceValue['valueQuote'][ $keyPathValue ],
				];
			}
		} unset( $sourceValue );
		//
		return $pathsQuote;
	}

	public static function usort( array &$array, string $keyPath, string $sort ) {
		if( $sort !== 'asc' && $sort !== 'desc' ){
			throw com\Lib\Err\Exception::makeOfNew( "sort({$sort}) 类型错误", com\Lib\Err\Code::$sysFunParamError );
		}
		//
		$isAsc = $sort === 'asc';
		//
		usort( $array, function( $aData, $bData ) use( $isAsc, $keyPath ) {
			$aValue = self::assignPathRead( $bData, $keyPath );
			$bValue = self::assignPathRead( $bData, $keyPath );
			//
			if( $isAsc ){
				return $aValue <=> $bValue;
			}else{
				return -( $aValue <=> $bValue ); // 取反
			}
		} );
	}

	/**
	 * 数组类型转换
	 * @param array $array
	 * @param string $keyPath
	 * @param string $convertType ['string'] ['int']
	 * @return mixed
	 * @throws com\Lib\Err\BaseException\Throw_
	 */
	public static function arrayTypeConvert( array &$array, string $keyPath, string $convertType ) {
		foreach( $array as &$arrayValue ){
			$valueQuote = &self::assignPathRead( $arrayValue, $keyPath, [
				'returnQuote' => 1,
			] );
			//
			switch( $convertType ){
				case 'string':
					$valueQuote = (string)$valueQuote;
					break;
				case 'int':
					$valueQuote = (int)$valueQuote;
					break;
				default:
					throw com\Lib\Err\Exception::makeOfNew( '未支持的转换类型：' . $convertType, com\Lib\Err\Code::$sysDataUnknown );
			}
		}
		//
		return $array;
	}

}
